package com.yima.baseproj.module.app.login;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.yima.baseproj.config.redis.lock.Callback;
import com.yima.baseproj.config.redis.lock.LockConstact;
import com.yima.baseproj.config.redis.lock.RedisLockUtil;
import com.yima.baseproj.module.app.user.AppUserEntity;
import com.yima.baseproj.module.app.user.AppUserService;
import com.yima.baseproj.module.config.BaseController;
import com.yima.baseproj.security.SecurityUtil;
import com.yima.baseproj.security.utils.jwt.JwtUtil;
import com.yima.baseproj.utils.wx.weapp.WxUtil;
import com.yima.baseproj.utils.wx.weapp.model.Code2SessionModel;
import com.yima.baseproj.utils.wx.weapp.model.UserPhoneModel;
import com.yima.baseproj.config.exception.type.ParamException;
import com.yima.baseproj.module.app.login.model.AppLoginMpWeixinParamModel;
import com.yima.baseproj.module.app.login.model.AppLoginMpWeixinPhoneParamModel;
import com.yima.baseproj.module.app.user.AppUserNoUtil;
import com.yima.baseproj.module.app.user.model.AppUserSexEnum;
import com.yima.baseproj.security.annotation.SecurityIgnoreUrl;
import com.yima.baseproj.security.exception.LoginAuthenticationException;
import com.yima.baseproj.security.model.UserLoginAuthModel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * @Author 一码
 * @createDate 2023/4/1 09:00
 * @contact 1424529270@qq.com
 */
@Api(tags = "登录管理")
@RestController
@RequestMapping("/api/app/login")
public class AppLoginController extends BaseController {

    @Resource
    private AppUserService appUserService;

    @Autowired
    private RedisLockUtil redisLockUtil;

    @Value("${upload.webBasePath}")
    private String webbasepath;

    @SecurityIgnoreUrl
    @ApiOperation("微信登录")
    @PostMapping(value = "/mpWeixin")
    public String mpWeixin(@RequestBody @Validated AppLoginMpWeixinParamModel paramModel){

        Code2SessionModel jscode2session = WxUtil.getJscode2session(paramModel.getCode());
        if(StrUtil.isBlank(jscode2session.getOpenid())){
            throw LoginAuthenticationException.LOGIN_JIEXI_ERROR;
        }

        //创建账号
        AppUserEntity appUserEntity = (AppUserEntity)redisLockUtil.execute(LockConstact.KEY_USER_CODE, 3, TimeUnit.SECONDS, new Callback() {
            @Override
            public Object onGetLock() {
                AppUserEntity userBean = appUserService.findByMpWeixinOpenId(jscode2session.getOpenid());
                if(userBean == null){
                    userBean = new AppUserEntity();
                    userBean.setUserNo(AppUserNoUtil.createUserNo());
                    userBean.setMpWeixinOpenId(jscode2session.getOpenid());
                    userBean.setNickName("点击编辑个人信息");
                    userBean.setPhone("");
                    userBean.setSex(AppUserSexEnum.WEIZHI.name());
                    userBean.setBirthday(DateUtil.date());
                    userBean.setHeadImg(String.format("%s/app/headimg/headimg.png",webbasepath));
                    appUserService.save(userBean);
                }

                return userBean;
            }

            @Override
            public Object onTimeout() {
                // TODO 未获取到锁（获取锁超时）后要做的事
                //log.info("没拿到锁");
                return null;
            }
        });
        if (appUserEntity == null) {
            throw LoginAuthenticationException.USER_COUNT_MORE;
        }
        String token = JwtUtil.createToken(appUserEntity.getId(), SecurityUtil.getClient());
        //设置用户信息
        UserLoginAuthModel authModel = new UserLoginAuthModel();
        authModel.setUserId(appUserEntity.getId());
        authModel.setClient(SecurityUtil.getClient());
        authModel.setRoleList(Arrays.asList());
        authModel.setPermissionList(Arrays.asList());
        authModel.setUserEntity(appUserEntity);

        SecurityUtil.setTokenToRedis(SecurityUtil.getClient(),appUserEntity.getId(),authModel);

        return token;
    }

    @SecurityIgnoreUrl
    @ApiOperation("微信手机号登录")
    @PostMapping(value = "/mpWeixinPhone")
    public String mpWeixinPhone(@RequestBody @Validated AppLoginMpWeixinPhoneParamModel paramModel){

        Code2SessionModel jscode2session = WxUtil.getJscode2session(paramModel.getLoginCode());
        if(StrUtil.isBlank(jscode2session.getOpenid())){
            throw LoginAuthenticationException.LOGIN_JIEXI_ERROR;
        }

        UserPhoneModel userPhoneModel = WxUtil.getUserPhonenumber(paramModel.getPhoneCode());
        if (userPhoneModel.getErrcode() != 0) {
            throw ParamException.getInstance("手机号获取失败，请稍后重试");
        }

        //创建账号
        AppUserEntity appUserEntity = (AppUserEntity)redisLockUtil.execute(LockConstact.KEY_USER_CODE, 3, TimeUnit.SECONDS, new Callback() {
            @Override
            public Object onGetLock() {
                AppUserEntity userBean = appUserService.findByMpWeixinOpenId(jscode2session.getOpenid());
                if(userBean == null){
                    userBean = new AppUserEntity();
                    userBean.setUserNo(AppUserNoUtil.createUserNo());
                    userBean.setMpWeixinOpenId(jscode2session.getOpenid());
                    userBean.setNickName("点击编辑个人信息");
                    userBean.setPhone(userPhoneModel.getPhoneInfo().getPhoneNumber());
                    userBean.setSex(AppUserSexEnum.WEIZHI.name());
                    userBean.setBirthday(DateUtil.date());
                    userBean.setHeadImg(String.format("%s/app/headimg/headimg.png",webbasepath));
                    appUserService.save(userBean);
                }

                return userBean;
            }

            @Override
            public Object onTimeout() {
                // TODO 未获取到锁（获取锁超时）后要做的事
                //log.info("没拿到锁");
                return null;
            }
        });
        if (appUserEntity == null) {
            throw LoginAuthenticationException.USER_COUNT_MORE;
        }
        String token = JwtUtil.createToken(appUserEntity.getId(), SecurityUtil.getClient());
        //设置用户信息
        UserLoginAuthModel authModel = new UserLoginAuthModel();
        authModel.setUserId(appUserEntity.getId());
        authModel.setClient(SecurityUtil.getClient());
        authModel.setRoleList(Arrays.asList());
        authModel.setPermissionList(Arrays.asList());
        authModel.setUserEntity(appUserEntity);

        SecurityUtil.setTokenToRedis(SecurityUtil.getClient(),appUserEntity.getId(),authModel);

        return token;
    }
}
